import Cesium from '../Ces/Cesium'
import WeFramebuffer from '../Ces/WeFramebuffer'
import WeGridMovableUpdatePositionShaders from './WeGridMovableUpdatePositionShaders'

class WeGridMovableUpdatePositions {
  framebuffers: WeFramebuffer[]
  command: any//Cesium.ComputeCommand
  constructor(options) {
    const { display, weUniform, context } = options
    this.framebuffers = [
      this.createFrameBuffer(
        context,
        weUniform.Properties.numLon,
        weUniform.Properties.numLat,
      ),
      this.createFrameBuffer(
        context,
        weUniform.Properties.numLon,
        weUniform.Properties.numLat,
      )
    ]

    this.setupCommand(display, weUniform, context)
  }

  getOutputTexture() {
    return this.framebuffers[0].getColorTexture(0)
  }

  createFrameBuffer(context, width, height) {
    const outputTexture = new Cesium.Texture({
      context,
      width,
      height,
      pixelFormat: Cesium.PixelFormat.RGBA,
      pixelDatatype: Cesium.PixelDatatype.FLOAT,
      sampler: Cesium.Sampler.NEAREST,
    })

    return new WeFramebuffer({
      context,
      colorTextures: [
        outputTexture
      ]
    })
  }

  setupCommand(display, weUniform, context) {
    const uniformMap = {
      u_particlesTexture: () => this.framebuffers[1].getColorTexture(0),
      u_rand_seed() {
        return Math.random()
      },
    }
    weUniform.setupUniformMap(uniformMap)
    display.setupUniformMap(uniformMap)
    const baseFragmentSource = display.getFragmentShaderSource(true, true, true)
    const fragmentShaderSource = `
      ${baseFragmentSource}
      ${weUniform.getSource(true)}
      ${WeGridMovableUpdatePositionShaders.fragmentShaderSource}
    `

    const that = this
    this.command = new Cesium.ComputeCommand({
      shaderProgram: Cesium.ShaderProgram.fromCache({
        context,
        vertexShaderSource: Cesium._shadersViewportQuadVS,
        fragmentShaderSource,
      }),
      vertexArray: context.getViewportQuadVertexArray(),
      uniformMap,
      preExecute(command) {
        command.framebuffer = that.framebuffers[0]
      },
      persists: true,
      owner: this,
    })
  }

  update(frameState) {
    if (!frameState.passes.render) return
    const tmp = this.framebuffers[0]
    this.framebuffers[0] = this.framebuffers[1]
    this.framebuffers[1] = tmp
    frameState.commandList.push(this.command)
  }

  destroy() {
    this.framebuffers.forEach(e => e.destroy())
    this.framebuffers.length = 0
    this.command?.shaderProgram.destroy()
    return Cesium.destroyObject(this)
  }

  isDestroyed() {
    return false
  }
}

export default WeGridMovableUpdatePositions
